package com.ydlclass.util.zookeeper;

import com.ydlclass.Constant;
import com.ydlclass.exceptions.ZookeeperException;
import lombok.extern.slf4j.Slf4j;
import org.apache.zookeeper.*;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CountDownLatch;

@Slf4j
public class ZookeeperUtil {

    /**
     * 使用默认配置创建zookeeper实例
     * @return zookeeper实例
     */
    public static ZooKeeper createZookeeper(){
        //定义连接参数
        String connectString = Constant.DEFAULT_ZK_CONNECT;
        //定义超时时间
        int timeout = Constant.TIME_OUT ;
        return createZookeeper(connectString,timeout);
    }


    public static ZooKeeper createZookeeper(String connectString,int timeout){
        CountDownLatch countDownLatch = new CountDownLatch(1);
        try {
            //zooKeeper = new ZooKeeper(connectString,timeout,null);
            //创建zookeeper实例，创建连接
            final ZooKeeper zooKeeper = new ZooKeeper(connectString, timeout,event -> {
                //只有连接成功才放行
                if(event.getState() == Watcher.Event.KeeperState.SyncConnected){
                    log.debug("客户端已经链接成功。");
                    countDownLatch.countDown();
                }
            });
            //等待链接成功
            countDownLatch.await();

            return zooKeeper;

        } catch (IOException | InterruptedException e) {
            log.error("创建zookeeper实例时，发生异常：",e);
            throw new ZookeeperException();
        }
    }

    /**
     * 创建一个节点的工具方法
     * @param zooKeeper 实例
     * @param node 节点
     * @param watcher watcher实例
     * @param createMode 节点类型
     * @return true: 成功创建  false: 存在 或者 异常抛出
     */
    public static Boolean createNode(ZooKeeper zooKeeper,ZookeeperNode node,Watcher watcher,CreateMode createMode){
        try {
            if(zooKeeper.exists(node.getNodePath(),watcher) == null){
                String result = zooKeeper.create(node.getNodePath(),null,
                        ZooDefs.Ids.OPEN_ACL_UNSAFE, createMode);
                log.info("节点{},成功创建。",result);
                return true;
            }else{
                if(log.isDebugEnabled()){
                    log.info("节点{},已经存在，无需创建",node.getNodePath());
                }
                return false;
            }
        } catch (KeeperException | InterruptedException e) {
            log.error("创建基础目录时发生异常",e);
            throw new ZookeeperException();
        }
    }

    /**
     * 判断节点是否存在
     * @param zk 实例
     * @param node 节点路径
     * @param watcher watcher实例
     * @return true 存在 false 不存在
     */
    public static boolean exists(ZooKeeper zk,String node,Watcher watcher){
        try {
            return zk.exists(node,watcher) != null;
        } catch (KeeperException | InterruptedException e) {
            log.error("判断节点{}是否存在时，发生异常",node,e);
            throw new ZookeeperException(e);
        }
    }

    /**
     * 关闭zookeeper的方法
     * @param zookeeper 实例
     */
    public static void close(ZooKeeper zookeeper){
        try {
            zookeeper.close();
        } catch (InterruptedException e) {
            log.error("关闭zookeeper时发生问题:",e);
            throw new ZookeeperException();
        }
    }

    /**
     * 查询一个节点的子元素
     * @param zooKeeper 实例
     * @param serviceNode 服务节点
     * @return 子元素列表
     */
    public static List<String> getChildren(ZooKeeper zooKeeper, String serviceNode,Watcher watcher) {
        try {
            return zooKeeper.getChildren(serviceNode, watcher);
        } catch (KeeperException | InterruptedException e) {
            log.error("获取节点{}的子元素时，发生异常.",serviceNode,e);
            throw new ZookeeperException(e);
        }
    }
}
